package web.sso.common.collections;

import web.sso.common.throwable.ConstructorNotAvailableError;

import java.util.*;
import java.util.function.Function;

/**
 * DATE: 2020/1/19
 * TIME: 4:55 下午
 *
 * @author：huangliming
 */
public class Sets extends Collections {
    /**
     * 构造器不允许调用
     * 抛出异常目的是防止反射获取
     */
    private Sets() {
        throw new ConstructorNotAvailableError(Sets.class);
    }

    /**
     * 重映射set
     * @return
     */
    public static <T, R> SetTransfer<T, R> reSet(Set<T> set, Function<T, R> mapper) {
        return new SetTransfer<>(set, mapper);
    }

    /**
     * 重映射set，不改变元素类型
     * @param set
     * @param <T>
     * @return
     */
    public static <T> SetTransfer<T, T> reSet(Set<T> set) {
        return reSet(set, e -> e);
    }

    /**
     * 从一个List生成Set
     * @param list
     * @return
     */
    public static <T, R> SetTransfer<T, R> fromList(List<T> list, Function<T, R> mapper) {
        return new SetTransfer<>(list, mapper);
    }

    /**
     * 从一个List生成set，不修改元素类型
     * @param list
     * @param <T>
     * @return
     */
    public static <T> SetTransfer<T, T> fromList(List<T> list) {
        return fromList(list, e -> e);
    }

    /**
     * 重映射实现类
     */
    public static class SetTransfer<T, R> {

        private Collection<T> collection;
        private Function<T, R> mapper;

        SetTransfer(Collection<T> collection, Function<T, R> mapper) {
            this.collection = collection;
            this.mapper = mapper;
        }

        /**
         * 将实例转化为HashSet
         * @return
         */
        public HashSet<R> hashSet() {
            HashSet<R> set = new HashSet<>(collection.size());
            reBuild(set);
            return set;
        }

        /**
         * 将实例转化为LinkedHashSet
         * @return
         */
        public LinkedHashSet<R> linkedHashSet() {
            LinkedHashSet<R> set = new LinkedHashSet<>(collection.size());
            reBuild(set);
            return set;
        }

        /**
         * 将实例转化为一个线程安全的Set
         * @return
         */
        public Set<R> synchronizedSet() {
            return java.util.Collections.synchronizedSet(hashSet());
        }

        /**
         * 重映射核心实现代码
         * @param set
         */
        private void reBuild(Set<R> set) {
            collection.forEach(e -> set.add(mapper.apply(e)));
        }
    }
}
